package com.fitso.model.dao;

import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSource;
import org.dbunit.DataSourceDatabaseTester;
import org.dbunit.IDatabaseTester;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.dataset.CompositeDataSet;
import org.dbunit.dataset.DataSetException;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
import org.dbunit.operation.DatabaseOperation;
import org.junit.After;
import org.junit.Before;

import com.fitso.model.context.ContextFactory;

/**
 * Base DB test that is used to setup test data. The local environment must have
 * a MySQL instance with the fitso tables already created. The MySQL instance
 * also needs to have a fitso_admin user with password = password setup
 * (permissions: READ, WRITE, DELET, UPDATE). This is used to prepare the tables
 * for testing.
 * 
 * @author timothystorm
 */
public abstract class DatabaseIntegrationTestUnit {
	private IDatabaseTester databaseTester;
	protected IDatabaseConnection conn;
	protected IDataSet dataSet;
	protected BasicDataSource dataSource;

	/**
	 * Prepares the DB for testing
	 * 
	 * @throws Exception
	 */
	@Before
	public void setUp() throws Exception {
		databaseTester = new DataSourceDatabaseTester(getDataSource());
		databaseTester.setDataSet(getDataSet());

		// wipe the database before inserting test data
		databaseTester.setSetUpOperation(DatabaseOperation.CLEAN_INSERT);

		// will call default setUpOperation
		databaseTester.onSetup();
	}

	@After
	public void tearDown() throws Exception {
		databaseTester.onTearDown();
	}

	protected DataSource getDataSource() {
		if (dataSource == null) {
			dataSource = (BasicDataSource) ContextFactory.getBean("BasicDataSource");
		}
		return dataSource;
	}

	protected IDataSet getDataSet() throws DataSetException {
		List<IDataSet> dataSets = new ArrayList<IDataSet>();

		try {
			for (String fileName : getDataFileNames()) {
				dataSets.add(new FlatXmlDataSetBuilder().build(new FileInputStream(fileName)));
			}
		}
		catch (Exception e) {
			throw new IllegalStateException(e);
		}
		return new CompositeDataSet(dataSets.toArray(new IDataSet[dataSets.size()]));
	}

	/**
	 * @return DBUnit test data file path
	 */
	abstract protected String[] getDataFileNames();
}
